/**
 * 
 */
package com.apttbc.looneytuner;

import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Handler;

/**
 * Class to perform the methods of a tuner
 * @author chadwickthebold
 *
 */
public class Audible extends Thread {
	
	public static final int AUDIO_INPUT_DEVICE = MediaRecorder.AudioSource.MIC;
    public static final int CHANNEL_CONFIG = android.media.AudioFormat.CHANNEL_CONFIGURATION_MONO;
    public static final int AUDIO_ENCODING = android.media.AudioFormat.ENCODING_PCM_16BIT;
    public static final int SAMPLE_RATE = 44100;
	
	private Handler thisHandler;
	private Runnable callback;
	private AudioRecord recordingTarget;
	private SoundDataUtils audioAnalyzer;
	
	private int bufferSize;
	private byte [] byteBuffer;
	
	//Frequency to report to the controlling Activity
	private double currentFrequency;
	private double currentMagnitude;
	
	//Create a new Audible object
	public Audible(Handler thisHandler, Runnable callback) {
		this.thisHandler = thisHandler;
		this.callback = callback;
		setupRecorder();
		currentFrequency = 0.0;
		currentMagnitude = 0.0;
	}
	
	//Set up the necessary audio recoding components for the tuner to function
	private void setupRecorder() {
		int bufferSizeMultiplier = 10;
		bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_ENCODING) * bufferSizeMultiplier;
		recordingTarget = new AudioRecord(AUDIO_INPUT_DEVICE, SAMPLE_RATE,
				CHANNEL_CONFIG, AUDIO_ENCODING, bufferSize);
		byteBuffer = new byte[bufferSize];
	}

	boolean fileWritten = false;
	//run the audio recorder and retrieve data from it.
	public void run() {
		recordingTarget.startRecording();
		byteBuffer = new byte[bufferSize];
		int n = 1;

		// loop to continually take in audio information/process it.
		while (n > 0 && recordingTarget != null) {
			
			if (recordingTarget != null)
				n = recordingTarget.read(byteBuffer, 0, bufferSize);
			
			audioAnalyzer = new SoundDataUtils(byteBuffer);

			// check if the audio information buffer is all zeroes.
			if (byteBuffer[0] != 0 && byteBuffer[10] != 0
					&& byteBuffer[100] != 0 && byteBuffer[1000] != 0) {

				// process the buffer
				currentFrequency = audioAnalyzer.getPrimaryFreq();
				currentMagnitude = audioAnalyzer.getMagnitude();
				if(!fileWritten && currentMagnitude > 100){
					audioAnalyzer.writeAudioToFile();
					fileWritten = true;
				}

				// post a callback to the handler, which SHOULD execute the
				// callback's run method
				thisHandler.post(callback);

				// stop recording, wait a bit, and then restart recording
					try {
						if (recordingTarget != null)
							recordingTarget.stop();
						
						Thread.sleep(20);
						
						if (recordingTarget != null)
							recordingTarget.startRecording();
						
					} catch (Exception e) {
						e.printStackTrace();
					}
				
			}

		}

	}
	
	byte[] getAudioBuffer() {
		
		return byteBuffer;
		
	}
	
	/**
	 * @return the bufferSize
	 */
	public int getBufferSize() {
		return bufferSize;
	}
	
	/**
	 * @return the currentFrequency
	 */
	public double getCurrentFrequency() {
		return currentFrequency;
	}

	/**
	 * @return the currentMagnitude
	 */
	public double getCurrentMagnitude() {
		return currentMagnitude;
	}

	//close all the resources associated with the audio recorder
	public void close() {
		recordingTarget.stop();
		recordingTarget.release();
		recordingTarget = null;
	}
	
}